---
sidebar_label: Using Unity
---
import AppCreationSteps from './partials/getting-started.mdx'
import ConsoleAccess from '../partials/callouts/console-access.mdx';
import SupportCallout from '../partials/callouts/support.mdx';
import DylibMacError from './partials/dylib-mac-error.mdx';

[Home](/docs/intro) > [Discord Social SDK](/docs/discord-social-sdk/overview) > {sidebar_label}

# Getting Started with Unity and the Discord Social SDK

## Overview

This guide will walk you through integrating the Discord Social SDK into a Unity project. By the end, you'll have a project that can:

- Authenticate users with Discord
- Set up logging and status monitoring
- Start the SDK and establish a connection
- Request the number of Discord friends the player has
- Set the player's rich presence for your game

### Prerequisites

Before starting, ensure you have:

- Unity 2021.3 or later

Let's walk through the steps in detail.

---

<AppCreationSteps />

---

## Step 4: Download the Social SDK for Unity

1. Click on the `Downloads` link under the Discord Social SDK section of the sidebar.
2. Select the latest version from the version dropdown and download the SDK for Unity.

:::info
A Unity sample project is available for download on this page, but we are not going to cover it in this guide. Explore it on your own after you finish this guide!
:::

---

## Step 5: Project Setup

Let's set up your Unity project to include the Social SDK package and add the necessary objects and scripts to use it.

1. Create a new 2D project in Unity Hub using Unity version 2021.3 or later
2. Either:
    1. Unzip the zip file in the Unity `Packages` folder, or
    2. Unzip the zip file and [Install Package from Disk](https://docs.unity3d.com/Manual/upm-ui-local.html). Make sure the folder is in a directory that won't get moved or deleted as your Unity project will load it from that location.
3. In your project add a `Scripts` folder and create a `DiscordManager.cs` script
4. Add the following code to `DiscordManager.cs`:
```cs
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;
}
```

6. Add an empty object to the scene (**GameObject > Create Empty**) called **DiscordManager** and attach the `DiscordManager.cs` script to it
7. Add a button to the scene **GameObject > UI > Legacy > Button**
8. Add text to the scene **GameObject > UI > Legacy > Text**
9. Position the button and text somewhere visible on the screen
10. Attach the button and text to the **DiscordManager** in the inspector
11. Run it!

This is all we'll need to get started! You shouldn't see anything happen, but if you run into any issues, check out the troubleshooting section before moving to the next step.

### Troubleshooting

- Make sure the Social SDK package was successfully added to Unity

<DylibMacError />
---

## Step 6: Setting Up SDK Event Handling

Let's add some event handlers to monitor what's happening with our Discord connection. We'll set up two important callbacks:

- A logging callback to see what the SDK is doing
- A status callback to know when we can start using Discord features

We'll start by adding the following code to your `DiscordManager.cs`:

```cs
    void Start()
    {
        client = new Client();

        // Modifying LoggingSeverity will show you more or less logging information
        client.AddLogCallback(OnLog, LoggingSeverity.Error);
        client.SetStatusChangedCallback(OnStatusChanged);

        // Make sure the button has a listener
        if (loginButton != null)
        {
            //loginButton.onClick.AddListener(StartOAuthFlow);
        }
        else
        {
            Debug.LogError("Login button reference is missing, connect it in the inspector!");
        }

        // Set initial status text
        if (statusText != null)
        {
            statusText.text = "Ready to login";
        }
        else
        {
            Debug.LogError("Status text reference is missing, connect it in the inspector!");
        }
    }

    private void OnLog(string message, LoggingSeverity severity)
    {
        Debug.Log($"Log: {severity} - {message}");
    }

    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }
    }
```

This will hook up the API status changes to your text in the game. Then we'll need to get your Client ID from the OAuth2 tab in the developer portal and paste it into the ClientID on the **DiscordManager** in the inspector.

### What These Callbacks Do

- The **logging callback** shows you what's happening behind the scenes and is a powerful tool for debugging
- The **status callback** tells you when you're connected and ready to use Discord features

:::info
The Unity plugin handles running the SDK callbacks for you in Unity, no need to use [`RunCallbacks`] like we do in the [C++ guide](/docs/discord-social-sdk/getting-started/using-c++).
:::

:::info
Most Discord features won't work until the status is `Ready`. The status callback lets you know when you can start using them.
:::

To get to a `Ready` state, we need to authenticate with Discord. Let's do that next.

---

## Step 7: Account Linking with Discord

In this step, we'll implement OAuth2 authentication to support account linking with Discord. This process will:

1. Open the Discord app or a browser window for Discord login
2. Get an authorization code
3. Exchange it for an access token
4. Connect to Discord

### Add the Authentication Code

To start we'll add this code to your `DiscordManager.cs`:
```cs
    private void StartOAuthFlow() {
        var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
        codeVerifier = authorizationVerifier.Verifier();
        
        var args = new AuthorizationArgs();
        args.SetClientId(clientId);
        args.SetScopes(Client.GetDefaultPresenceScopes());
        args.SetCodeChallenge(authorizationVerifier.Challenge());
        client.Authorize(args, OnAuthorizeResult);
    }

    private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
        Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
        if (!result.Successful()) {
            return;
        }
        GetTokenFromCode(code, redirectUri);
    }

    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {});
    }
```

and then we'll uncomment `loginButton.onClick.AddListener(StartOAuthFlow);` in your `Start()` method
```cs
        if (loginButton != null)
        {
            loginButton.onClick.AddListener(StartOAuthFlow);
        }
```

### What's Happening Here?

1. We create a code verifier for OAuth2 PKCE security
2. Set up authorization arguments with your app ID and required scopes
3. Start the auth flow with [`Client::Authorize`], which opens a browser
4. When authorized, we exchange the code for an access token

:::warn
Never log or store access tokens insecurely! They should be treated as sensitive credentials.
:::

### Testing It Out

Now, if you press play and click the button, it should start the OAuth flow! You'll be redirected to your browser to log in and authorize the game. There will be some logging to the console, but the status won't change yet.

### Troubleshooting

- Make sure you've uncommented `loginButton.onClick.AddListener(StartOAuthFlow);` if the button doesn't seem to do anything
- Double check your `ClientId` is correct
- Ensure you've added the redirect URL in your Discord Developer Portal
- Check the console for specific error messages

<Collapsible title="DiscordManager.cs up to this point" icon="code">
```cs
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;

        void Start()
    {
        client = new Client();

        // Modifying LoggingSeverity will show you more or less logging information
        client.AddLogCallback(OnLog, LoggingSeverity.Error);
        client.SetStatusChangedCallback(OnStatusChanged);

        // Make sure the button has a listener
        if (loginButton != null)
        {
            loginButton.onClick.AddListener(StartOAuthFlow);
        }
        else
        {
            Debug.LogError("Login button reference is missing, connect it in the inspector!");
        }

        // Set initial status text
        if (statusText != null)
        {
            statusText.text = "Ready to login";
        }
        else
        {
            Debug.LogError("Status text reference is missing, connect it in the inspector!");
        }
    }

    private void OnLog(string message, LoggingSeverity severity)
    {
        Debug.Log($"Log: {severity} - {message}");
    }

    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }
    }
    
    private void StartOAuthFlow() {
        var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
        codeVerifier = authorizationVerifier.Verifier();
        
        var args = new AuthorizationArgs();
        args.SetClientId(clientId);
        args.SetScopes(Client.GetDefaultPresenceScopes());
        args.SetCodeChallenge(authorizationVerifier.Challenge());
        client.Authorize(args, OnAuthorizeResult);
    }

    private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
        Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
        if (!result.Successful()) {
            return;
        }
        GetTokenFromCode(code, redirectUri);
    }

    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {});
    }
}
```
</Collapsible>

---

## Step 8: Connect the SDK to Discord

Now that we have our access token, let's connect to Discord!

To start, we'll add this code to your `DiscordManager.cs`:

```cs
    private void OnReceivedToken(string token) {
        Debug.Log("Token received: " + token);
        client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
    }

    private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
```

Then we'll update `GetTokenFromCode` to call these functions when it completes:

```cs
    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {
                            if (token != "") {
                                OnReceivedToken(token);
                            } else {
                                OnRetrieveTokenFailed();
                            }
                        });
    }
```

### What's Happening Here?

1. [`Client::UpdateToken`] tells the SDK to use our access token for Discord API calls
2. Once the token is updated, we call [`Client::Connect`] in the callback
3. The SDK will begin connecting asynchronously
4. Our status text will tell you when the SDK is ready!

### Testing the Connection

Press play and click the button again to log in and authorize the game. This time you should see the status text change as it goes through the OAuth flow, and it should end up `Ready`

### Troubleshooting

If you don't see `Ready` status:

- Check that your access token is valid
- Ensure you have internet connectivity
- Look for error messages from the SDK in the console
- Verify your `ClientID` set in the inspector is correct


<Collapsible title="DiscordManager.cs up to this point" icon="code">
```cs
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;

        void Start()
    {
        client = new Client();

        // Modifying LoggingSeverity will show you more or less logging information
        client.AddLogCallback(OnLog, LoggingSeverity.Error);
        client.SetStatusChangedCallback(OnStatusChanged);

        // Make sure the button has a listener
        if (loginButton != null)
        {
            loginButton.onClick.AddListener(StartOAuthFlow);
        }
        else
        {
            Debug.LogError("Login button reference is missing, connect it in the inspector!");
        }

        // Set initial status text
        if (statusText != null)
        {
            statusText.text = "Ready to login";
        }
        else
        {
            Debug.LogError("Status text reference is missing, connect it in the inspector!");
        }
    }

    private void OnLog(string message, LoggingSeverity severity)
    {
        Debug.Log($"Log: {severity} - {message}");
    }

    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }
    }

    private void StartOAuthFlow() {
        var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
        codeVerifier = authorizationVerifier.Verifier();
        
        var args = new AuthorizationArgs();
        args.SetClientId(clientId);
        args.SetScopes(Client.GetDefaultPresenceScopes());
        args.SetCodeChallenge(authorizationVerifier.Challenge());
        client.Authorize(args, OnAuthorizeResult);
    }

    private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
        Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
        if (!result.Successful()) {
            return;
        }
        GetTokenFromCode(code, redirectUri);
    }

    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {
                            if (token != "") {
                                OnReceivedToken(token);
                            } else {
                                OnRetrieveTokenFailed();
                            }
                        });
    }

    private void OnReceivedToken(string token) {
        Debug.Log("Token received: " + token);
        client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
    }

    private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
}
```
</Collapsible>

Now that your client is in a ready state, we can start implementing Discord social features.

---

## Step 9: Access Discord Relationships

Let's access the user's Discord relationships (friends list) and display the count. This will help you understand how to access and use Discord data in your game.

Lets add some new code to your `DiscordManager.cs`:

```cs
    private void ClientReady()
    {
        Debug.Log($"Friend Count: {client.GetRelationships().Count()}");
    }
```

We want to call this when the client is ready to use which we'll know in our `OnStatusChanged` method:

```cs
    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }

        if (status == Client.Status.Ready)
        {
            ClientReady();
        }
    }
```

### What This Code Does

When the client status is `Ready,` it'll call our `ClientReady` function, which will call [`Client::GetRelationships`], returning us a list of all the player's friends. We then log the number of friends directly to the console.

### Testing It Out

Hit play and then click the button. Once the OAuth flow completes and you see the status hit `Ready` check the console to see the output!

### Example Output

```
Friend Count: 42
```

### Troubleshooting

- Verify your OAuth2 scopes include relationships access
- Ensure you're connected (status is `Ready`)
- Check that you have friends on Discord
- Look for errors in the logging callback

Next, we'll learn how to show your game's activity on Discord with Rich Presence!

<Collapsible title="DiscordManager.cs up to this point" icon="code">
```cs
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;

        void Start()
    {
        client = new Client();

        // Modifying LoggingSeverity will show you more or less logging information
        client.AddLogCallback(OnLog, LoggingSeverity.Error);
        client.SetStatusChangedCallback(OnStatusChanged);

        // Make sure the button has a listener
        if (loginButton != null)
        {
            loginButton.onClick.AddListener(StartOAuthFlow);
        }
        else
        {
            Debug.LogError("Login button reference is missing, connect it in the inspector!");
        }

        // Set initial status text
        if (statusText != null)
        {
            statusText.text = "Ready to login";
        }
        else
        {
            Debug.LogError("Status text reference is missing, connect it in the inspector!");
        }
    }

    private void OnLog(string message, LoggingSeverity severity)
    {
        Debug.Log($"Log: {severity} - {message}");
    }

    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }

        if (status == Client.Status.Ready)
        {
            ClientReady();
        }
    }

    private void ClientReady()
    {
        Debug.Log($"Friend Count: {client.GetRelationships().Count()}");
    }


    private void StartOAuthFlow() {
        var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
        codeVerifier = authorizationVerifier.Verifier();
        
        var args = new AuthorizationArgs();
        args.SetClientId(clientId);
        args.SetScopes(Client.GetDefaultPresenceScopes());
        args.SetCodeChallenge(authorizationVerifier.Challenge());
        client.Authorize(args, OnAuthorizeResult);
    }

    private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
        Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
        if (!result.Successful()) {
            return;
        }
        GetTokenFromCode(code, redirectUri);
    }

    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {
                            if (token != "") {
                                OnReceivedToken(token);
                            } else {
                                OnRetrieveTokenFailed();
                            }
                        });
    }

    private void OnReceivedToken(string token) {
        Debug.Log("Token received: " + token);
        client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
    }

    private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
}
```
</Collapsible>

---

## Step 10: Set Rich Presence

Let's show your game's activity on Discord using Rich Presence. This feature lets players see what others are doing in your game directly in their Discord friends list.

Update your `ClientReady` method with this code:

```cs
    private void ClientReady()
    {
            Debug.Log($"Friend Count: {client.GetRelationships().Count()}");

            Activity activity = new Activity();
            activity.SetType(ActivityTypes.Playing);
            activity.SetState("In Competitive Match");
            activity.SetDetails("Rank: Diamond II");
            client.UpdateRichPresence(activity, (ClientResult result) => {
                if (result.Successful()) {
                    Debug.Log("Rich presence updated!");
                } else {
                    Debug.LogError("Failed to update rich presence");
                }
            });
    }
```

### What This Code Does

1. Creates an [`Activity`] object to represent what the player is doing
2. Sets basic information like:
  - The activity type (Playing)
  - Current state ("In Competitive Match")
  - Additional details ("Rank: Diamond II")
3. Updates your rich presence on Discord

### Testing It Out

Hit play and then click the button. Once the OAuth flow is complete, you will see the status hit `Ready`. The console will tell you if setting rich presence was successful, and you can check your Discord profile to see it!

### Troubleshooting

If you don't see your presence:
- Ensure you're connected (status is `Ready`)
- Check the console for error messages
- Verify your activity settings are valid
- Make sure you're not invisible on Discord

--- 

<Collapsible title="The full DiscordManager.cs" icon="code">
```cs
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;

        void Start()
    {
        client = new Client();

        // Modifying LoggingSeverity will show you more or less logging information
        client.AddLogCallback(OnLog, LoggingSeverity.Error);
        client.SetStatusChangedCallback(OnStatusChanged);

        // Make sure the button has a listener
        if (loginButton != null)
        {
            loginButton.onClick.AddListener(StartOAuthFlow);
        }
        else
        {
            Debug.LogError("Login button reference is missing, connect it in the inspector!");
        }

        // Set initial status text
        if (statusText != null)
        {
            statusText.text = "Ready to login";
        }
        else
        {
            Debug.LogError("Status text reference is missing, connect it in the inspector!");
        }
    }

    private void OnLog(string message, LoggingSeverity severity)
    {
        Debug.Log($"Log: {severity} - {message}");
    }

    private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
    {
        Debug.Log($"Status changed: {status}");
        statusText.text = status.ToString();
        if(error != Client.Error.None)
        {
            Debug.LogError($"Error: {error}, code: {errorCode}");
        }

        if (status == Client.Status.Ready)
        {
            ClientReady();
        }
    }

    private void ClientReady()
    {
            Debug.Log($"Friend Count: {client.GetRelationships().Count()}");

            Activity activity = new Activity();
            activity.SetType(ActivityTypes.Playing);
            activity.SetState("In Competitive Match");
            activity.SetDetails("Rank: Diamond II");
            client.UpdateRichPresence(activity, (ClientResult result) => {
                if (result.Successful()) {
                    Debug.Log("Rich presence updated!");
                } else {
                    Debug.LogError("Failed to update rich presence");
                }
            });
    }

    private void StartOAuthFlow() {
        var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
        codeVerifier = authorizationVerifier.Verifier();
        
        var args = new AuthorizationArgs();
        args.SetClientId(clientId);
        args.SetScopes(Client.GetDefaultPresenceScopes());
        args.SetCodeChallenge(authorizationVerifier.Challenge());
        client.Authorize(args, OnAuthorizeResult);
    }

    private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
        Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
        if (!result.Successful()) {
            return;
        }
        GetTokenFromCode(code, redirectUri);
    }

    private void GetTokenFromCode(string code, string redirectUri) {
        client.GetToken(clientId,
                        code,
                        codeVerifier,
                        redirectUri,
                        (result, token, refreshToken, tokenType, expiresIn, scope) => {
                            if (token != "") {
                                OnReceivedToken(token);
                            } else {
                                OnRetrieveTokenFailed();
                            }
                        });
    }

    private void OnReceivedToken(string token) {
        Debug.Log("Token received: " + token);
        client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
    }

    private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
}
```
</Collapsible>

---

## Conclusion

Congratulations! You've successfully integrated the Discord Social SDK into Unity. Let's review what you've accomplished:

### What You've Built

- ✅ Created a Discord application and configured OAuth2
- ✅ Set up SDK logging and status monitoring
- ✅ Implemented user authentication flow
- ✅ Retrieved Discord relationships data
- ✅ Added Rich Presence support

### Key Concepts Learned

- How to initialize and configure the Discord SDK
- Managing authentication and connections
- Working with Discord's social features
- Handling asynchronous callbacks
- Monitoring SDK status and events

---

## Next Steps

### Social SDK Unity sample

Check out our [in depth sample for using the Social SDK in Unity](https://github.com/discord/social-sdk-unity-sample) following the best practices laid out in these guides. It contains easy to drop in prefabs with both code and UI to quickly integrate Discord's social features into your game.

![Video showing off the Unity sample with the Discord Social SDK](images/social-sdk/getting-started/unity-sample-preview.webp)

### Continuing On

Follow these guides to dive deeper into the features of the Discord Social SDK.

<Container>
  <Card title="Creating a Unified Friends List" link="/docs/discord-social-sdk/development-guides/creating-a-unified-friends-list" icon="ListViewIcon">
    Create a unified friends list combining Discord and game-specific friendships
  </Card>
  <Card title="Setting Rich Presence" link="/docs/discord-social-sdk/development-guides/setting-rich-presence" icon="UserStatusIcon">
    Customize your game's rich presence to show more advanced information and game invites
  </Card>
  <Card title="Managing Game Invites" link="/docs/discord-social-sdk/development-guides/managing-game-invites" icon="InboxIcon">
    Allow players to invite friends to join their game session or party.
  </Card>
</Container>

<SupportCallout />

---

## Change Log

| Date           | Changes         |
|----------------|-----------------|
| March 17, 2025 | Initial release |

{/* Autogenerated Reference Links */}
[`Activity`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Activity.html#ae793d9adbe16fef402b859ba02bee682
[`Client::Authorize`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ace94a58e27545a933d79db32b387a468
[`Client::Connect`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a873a844c7c4c72e9e693419bb3e290aa
[`Client::GetRelationships`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ad481849835cd570f0e03adafcf90125d
[`Client::UpdateToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a606b32cef7796f7fb91c2497bc31afc4
[`RunCallbacks`]: https://discord.com/developers/docs/social-sdk/namespacediscordpp.html#ab5dd8cf274f581ee1885de5816be3c29